// Types, determining compatibile SQL & .NET types, conversions.

using System;
using System.Data;
using System.Data.SqlClient;

namespace BizElements.Core
{
	/// <summary>
	/// Provides static methods for type conversions and testing.
	/// </summary>
	internal static class TypeUtil
	{
		#region .NET Type converters.

		/// <summary>
		/// Determines compatibile .NET type for the given DbType.
		/// </summary>
		/// <param name="dbType">DbType.</param>
		/// <returns>.NET type.</returns>
        internal static Type NetTypeFrom(DbType dbType)
		{
			SqlParameter par = new SqlParameter();
			par.DbType = dbType;
			SqlDbType sqlType = par.SqlDbType;

			return NetTypeFrom(sqlType);
		}

		/// <summary>
		/// Determines compatibile .NET type for the given SqlDbType.
		/// </summary>
		/// <param name="sqlDbType">SqlDbType.</param>
		/// <returns>.NET type.</returns>
        internal static Type NetTypeFrom(SqlDbType sqlDbType)
		{
			switch (sqlDbType)
			{
					// Most common first.
				case SqlDbType.Int:
					return typeof(int);
				case SqlDbType.VarChar:
					return typeof(string);
				case SqlDbType.DateTime:
					return typeof(DateTime);
				case SqlDbType.Char:
					return typeof(string);
				case SqlDbType.Float:
					return typeof(double);

				case SqlDbType.BigInt:
					return typeof(long);
				case SqlDbType.Binary:
					return typeof(byte[]);
				case SqlDbType.Bit:
					return typeof(bool);									
				case SqlDbType.Decimal:
					return typeof(decimal);				
				case SqlDbType.Image:
					return typeof(byte[]);					
				case SqlDbType.Money:
					return typeof(decimal);
				case SqlDbType.NChar:
					return typeof(string);
				case SqlDbType.NText:
					return typeof(string);
				case SqlDbType.NVarChar:
					return typeof(string);
				case SqlDbType.Real:
					return typeof(float);
				case SqlDbType.SmallDateTime:
					return typeof(DateTime);
				case SqlDbType.SmallInt:
					return typeof(short);
				case SqlDbType.SmallMoney:
					return typeof(decimal);
				case SqlDbType.Text:
					return typeof(string);
				case SqlDbType.Timestamp:
					return typeof(byte[]);
				case SqlDbType.TinyInt:
					return typeof(byte);
				case SqlDbType.UniqueIdentifier:
					return typeof(Guid);
				case SqlDbType.VarBinary:
					return typeof(byte[]);					
				case SqlDbType.Variant:
					return typeof(object);
					
				default:
					return typeof(object);
			}
		}

		#endregion

		#region DbType converters.
		
		/// <summary>
		/// Determines compatibile DbType type for the given .NET type.
		/// </summary>
		/// <param name="dotNetType">.NET type.</param>
		/// <returns>DbType.</returns>
        internal static DbType DbTypeFrom(Type dotNetType)
		{
			// Most common first.

			if (dotNetType == typeof(int))
				return DbType.Int32;
			else if (dotNetType == typeof(string))
				return DbType.AnsiString;
			else if (dotNetType == typeof(DateTime))
				return DbType.DateTime;	
			else if (dotNetType == typeof(bool))
				return DbType.Boolean;
			else if (dotNetType == typeof(double))
				return DbType.Double;	
			else if (dotNetType == typeof(float))
				return DbType.Single;
			else if (dotNetType == typeof(decimal))				
				return DbType.Decimal;
			else if (dotNetType == typeof(char[]))
				return DbType.AnsiString;
			else if (dotNetType == typeof(long))
				return DbType.Int64;
			else if (dotNetType == typeof(byte[]))
				return DbType.Binary;			
			else if (dotNetType == typeof(short))
				return DbType.Int16;			
			else if (dotNetType == typeof(Guid))
				return DbType.Guid;			
			else if (dotNetType == typeof(char))
				return DbType.AnsiString;
			else if (dotNetType == typeof(byte))
				return DbType.Byte;
			else if (dotNetType == typeof(object))
				return DbType.Object;
			else
				return DbType.Object;
        }

        #endregion

        #region Type classes.

        /// <summary>
		/// Indicates whether the given type is an integer number (Int32, Byte, Long etc.).
		/// </summary>
		/// <param name="t">Type to be tested.</param>
		/// <returns>True if a given type is an integral type; false otherwise.</returns>
		public static bool IsInteger(Type t)
		{			
			if (t == typeof(Int32)  ||  t == typeof(Byte)  ||  t == typeof(Int16)  ||  t == typeof(Int64)  ||  t == typeof(SByte)  ||  t == typeof(UInt16)  ||  t == typeof(UInt32)  ||  t == typeof(Int64))
				return true;
			else
				return false;			
		}

		/// <summary>
		/// Indicates wheter the given type is a floating point number (Single, Double, Decimal).
		/// </summary>
		/// <param name="t">Type to be tested.</param>
		/// <returns>True if a given type is a floating point type; false otherwise.</returns>
		public static bool IsFloatingPointNumber(Type t)
		{
			if (t == typeof(Single)  ||  t == typeof(Double)  ||  t == typeof(Decimal))
				return true;
			else
				return false;		
		}

		/// <summary>
		/// Indicates whether the given type is a number (integer or real number).
		/// </summary>
		/// <param name="t">Type to be tested.</param>
		/// <returns>True if a given type is a numeric type; false otherwise.</returns>
		public static bool IsNumber(Type t)
		{
			if (IsFloatingPointNumber(t)  ||  IsInteger(t))
				return true;
			else
				return false;			
		}

		/// <summary>
		/// Indicates whether the given type is a date type.
		/// </summary>	
		/// <param name="t">Type to be tested.</param>
		/// <returns>True if a given type is a date type; false otherwise.</returns>
		public static bool IsDate(Type t)
		{
			if (t == typeof(DateTime))
				return true;
			else
				return false;		
		}

		/// <summary>
		/// Indicates whether the given type is textual (String, Char, Char[]).
		/// </summary>
		/// <param name="t">Type to be tested.</param>
		/// <returns>True if a given type is a textual type; false otherwise.</returns>
		public static bool IsText(Type t)
		{
			if (t == typeof(String)  ||  t == typeof(Char) ||  t == typeof(Char[]))
				return true;
			else
				return false;		
		}

		#endregion
	}
}
